package com.hemerasolutions.v2trainer.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.hemerasolutions.v2trainer.dao.ExceptionDao;
import com.hemerasolutions.v2trainer.dao.interfaces.EquipmentDaoInterface;
import com.hemerasolutions.v2trainer.dao.interfaces.LibraryDaoInterface;
import com.hemerasolutions.v2trainer.dao.interfaces.PhotoDaoInterface;
import com.hemerasolutions.v2trainer.dao.interfaces.VideoDaoInterface;
import com.hemerasolutions.v2trainer.model.equipment.VersionableEquipment;
import com.hemerasolutions.v2trainer.model.exercise.Equipment;
import com.hemerasolutions.v2trainer.model.library.Library;
import com.hemerasolutions.v2trainer.model.multimedia.Photo;
import com.hemerasolutions.v2trainer.model.multimedia.Video;
import com.hemerasolutions.v2trainer.service.interfaces.EquipmentServiceInterface;


@Service("equipmentService")
public class EquipmentService extends BaseService implements EquipmentServiceInterface {

	private static final long serialVersionUID = 1L;

	@Autowired
	private PhotoDaoInterface photoDao;

	@Autowired
	private VideoDaoInterface videoDao;
	
	@Autowired
	private LibraryDaoInterface libraryDao;
	
	@Autowired
	private EquipmentDaoInterface equipmentDao;
	
	
	public EquipmentService() {
		super();
	}


	@PostConstruct
	public void init(){
		
	}



	@Override
	public Photo readDefaultPhoto(){

		Photo photo, photo2;
		photo = photoDao.findByLocation("default_equipment.jpg"); 

		photo2 = new Photo(photo);
		
		return photo2;
		
	}

	@Override
	public Video readDefaultVideo(){
		Video video, video2;
		video = videoDao.getByName("v2trainer_default_equipment");
		video2 = new Video(video);
		video2.setName("");

		return video2;
	}
	

	@Override
	public List<Photo> readDefaultPhotos() {

		List<Photo> photos = new ArrayList<Photo>();
		
		photos.add(this.readDefaultPhoto());
		
		return photos;
	}


	@Override
	public List<Video> readDefaultVideos() {

		List<Video> videos = new ArrayList<Video>();
		
		videos.add(this.readDefaultVideo());
		
		return videos;
	}

	

	@Override
	public List<Equipment> findEquipments(Map<String, Object> fields,
			List<Library> librarys) {

		List<Equipment> equipments = new ArrayList<Equipment>();
		
		for(Library library:librarys){
			for(VersionableEquipment vEquipment :library.getVersionableEquipments()){
				for(Equipment equipment:vEquipment.getEquipmentVersions()){
					if(this.equipmentMatch(equipment, fields)){
						if(!equipments.contains(equipment)){
							equipments.add(equipment);
						}
					}
				}
			}
		}

			
		return equipments;
	}
	
	@Override
	public List<Equipment> filterEquipments(Map<String, Object> fields,
			List<Equipment> equipments) {

		
		List<Equipment> result = new ArrayList<Equipment>();
		
		
		for(Equipment equipment:equipments){
			if(this.equipmentMatch(equipment,fields)){
				result.add(equipment);
			}
		}
		
		return result;
	}


	private boolean equipmentMatch(Equipment equipment, Map<String, Object> fields) {

		Calendar cal1 = Calendar.getInstance();
		Calendar cal2 = Calendar.getInstance();

		if(fields.containsKey("name")){
			if(! equipment.getName().toUpperCase().contains(((String)fields.get("name")).toUpperCase())){
				return false;
			}
		}
		
		if(fields.containsKey("obs")){
			if(! equipment.getName().toUpperCase().contains(((String)fields.get("obs")).toUpperCase())){
				return false;
			}
		}

		if(fields.containsKey("description")){
			if(! equipment.getName().toUpperCase().contains(((String)fields.get("description")).toUpperCase())){
				return false;
			}
		}

		if(fields.containsKey("begCreatedAt")){

			cal1.setTime(equipment.getCreatedAt());
			cal2.setTime((Date)fields.get("begCreatedAt"));

			if(! (cal1.get(Calendar.YEAR) >= cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) >= cal2.get(Calendar.DAY_OF_YEAR))){
				return false;
			}
		}
			

		if(fields.containsKey("endCreatedAt")){

			cal1.setTime(equipment.getCreatedAt());
			cal2.setTime((Date)fields.get("endCreatedAt"));

			if(! (cal1.get(Calendar.YEAR) <= cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) <= cal2.get(Calendar.DAY_OF_YEAR))){
				return false;
			}			
		}
		
		if(fields.containsKey("begChangedAt")){
			cal1.setTime(equipment.getCreatedAt());
			cal2.setTime((Date)fields.get("begChangedAt"));

			if(! (cal1.get(Calendar.YEAR) >= cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) >= cal2.get(Calendar.DAY_OF_YEAR))){
				return false;
			}
			
		}

		if(fields.containsKey("endChangedAt")){

			cal1.setTime(equipment.getCreatedAt());
			cal2.setTime((Date)fields.get("endChangedAt"));

			if(! (cal1.get(Calendar.YEAR) <= cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) <= cal2.get(Calendar.DAY_OF_YEAR))){
				return false;
			}						
		}

		
		return true;

	}
	
	private boolean equipmentMatch(VersionableEquipment versionableEquipment, Map<String, Object> fields) {

		Calendar cal1 = Calendar.getInstance();
		Calendar cal2 = Calendar.getInstance();

		
		for(Equipment equipment:versionableEquipment.getEquipmentVersions()){
			if(fields.containsKey("name")){
				if(! equipment.getName().toUpperCase().contains(((String)fields.get("name")).toUpperCase())){
					return false;
				}
			}
			
			if(fields.containsKey("obs")){
				if(! equipment.getName().toUpperCase().contains(((String)fields.get("obs")).toUpperCase())){
					return false;
				}
			}

			if(fields.containsKey("description")){
				if(! equipment.getName().toUpperCase().contains(((String)fields.get("description")).toUpperCase())){
					return false;
				}
			}

			if(fields.containsKey("begCreatedAt")){

				cal1.setTime(equipment.getCreatedAt());
				cal2.setTime((Date)fields.get("begCreatedAt"));

				if(! (cal1.get(Calendar.YEAR) >= cal2.get(Calendar.YEAR) &&
	                cal1.get(Calendar.DAY_OF_YEAR) >= cal2.get(Calendar.DAY_OF_YEAR))){
					return false;
				}
			}
				

			if(fields.containsKey("endCreatedAt")){

				cal1.setTime(equipment.getCreatedAt());
				cal2.setTime((Date)fields.get("endCreatedAt"));

				if(! (cal1.get(Calendar.YEAR) <= cal2.get(Calendar.YEAR) &&
	                cal1.get(Calendar.DAY_OF_YEAR) <= cal2.get(Calendar.DAY_OF_YEAR))){
					return false;
				}			
			}
			
			if(fields.containsKey("begChangedAt")){
				cal1.setTime(equipment.getCreatedAt());
				cal2.setTime((Date)fields.get("begChangedAt"));

				if(! (cal1.get(Calendar.YEAR) >= cal2.get(Calendar.YEAR) &&
	                cal1.get(Calendar.DAY_OF_YEAR) >= cal2.get(Calendar.DAY_OF_YEAR))){
					return false;
				}
				
			}

			if(fields.containsKey("endChangedAt")){

				cal1.setTime(equipment.getCreatedAt());
				cal2.setTime((Date)fields.get("endChangedAt"));

				if(! (cal1.get(Calendar.YEAR) <= cal2.get(Calendar.YEAR) &&
	                cal1.get(Calendar.DAY_OF_YEAR) <= cal2.get(Calendar.DAY_OF_YEAR))){
					return false;
				}						
			}

			
			return true;			
		}

		return false;
	}


	@Override
	public List<Equipment> searchEquipments(Map<String, Object> fields) {

		return equipmentDao.searchEquipments(fields);
			
	}


	@Override
	public Equipment createEquipment(Equipment equipment) throws ExceptionService {
		try {
			equipment = equipmentDao.create(equipment);
		} catch (ExceptionDao e) {
			e.printStackTrace();
			throw new ExceptionService(e);
		} catch (ExceptionService e) {
			throw e;
		}
	
	return equipment;
		
	}


	@Override
	public Equipment saveEquipment(Equipment equipment) throws ExceptionService {
		try {
			equipment = equipmentDao.save(equipment);
		} catch (ExceptionDao e) {
			e.printStackTrace();
			throw new ExceptionService(e);
		} catch (ExceptionService e) {
			throw e;
		}
	
	return equipment;
		
	}


	@Override
	public void deleteEquipment(Equipment equipment) throws ExceptionService {
		try {
			equipmentDao.delete(equipment);
		} catch (ExceptionDao e) {
			e.printStackTrace();
			throw new ExceptionService(e);
		} catch (ExceptionService e) {
			throw e;
		}
		
	}


	@Override
	public Equipment readEquipment(Equipment equipment) {
		return equipmentDao.getById(equipment.getId());
	}


	@Override
	public Photo savePhoto(Photo photo) {
		if(photo != null){
			return photoDao.save(photo);
		}else{
			return photo;
		}

	}

	@Override
	public Video saveVideo(Video video) {
		if(video != null){
			return videoDao.save(video);
		}else{
			return video;
		}

	}
	



}
